package com.example.maybeaccount.Mode;

import android.app.Activity;
import android.content.Context;
import android.util.Log;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.HashMap;

/**
 * 账单管理器，用于账单临时存储与运算
 */
public class ItemManager implements Serializable {
    /**
     * 所有账单,但不包括信贷，建立时已经计算好收入和支出
     */
    private ArrayList<Item> allItemListWithoutAccount = new ArrayList<Item>();
    /**
     * 某个账户的所有账单，用于对接前端Adapter
     */
    private ArrayList<Item> allItemList = new ArrayList<Item>();
    /**
     * 统计列表
     */
    private ArrayList<Item> monthItemList = new ArrayList<Item>();
    private ArrayList<Item> yearItemList = new ArrayList<Item>();
    private ArrayList<Item> dayItemList = new ArrayList<Item>();
    private ArrayList<Item> accountItemList = new ArrayList<Item>();
    private ArrayList<Item> creditItemList = new ArrayList<>();
    private ArrayList<Item> memberItemList = new ArrayList<>();
    /**
     * 所有账户列表
     */
    private ArrayList<Account> accountList = new ArrayList<Account>();

    private double allAmount = 0;
    private double allExpend = 0;
    private double allIncome = 0;
    private boolean monthHasBeenCal = false;
    private boolean yearHasBeenCal = false;
    private boolean accountHasBeenCal = false;
    private boolean dayHasBeenCal = false;

    /**
     * （图表)筛选模式
     */
    public static final int SCREEN_MODE_CLASS1 = 0;
    public static final int SCREEN_MODE_CLASS2 = 1;
    public static final int SCREEN_MODE_ACCOUNT = 2;
    public static final int SCREEN_MODE_MEMBER = 3;
    public static final int MODE_INCOME = 0;
    public static final int MODE_EXPEND = 1;
    public static final int MODE_IN_AND_OUT = 2;
    //public boolean able = false;


    /**
     * 初始化对象，传入所有账单、账户
     * @param itemList
     */
    public void setItem(ArrayList<Item> itemList){
        for(int i = 0;i < itemList.size();i ++){
            Item tempItem = itemList.get(i);
            if(tempItem.getMode() == Item.MODE_CREDIT || tempItem.getMode() == Item.MODE_CREDIT_PAYBACK){
                creditItemList.add(tempItem);
            }else{
                allItemListWithoutAccount.add(tempItem);
            }
        }
        //this.allItemListWithoutAccount = itemList;
        calIncomeAndExpend();
        //able = true;
        //sortItem();
    }
    public void setAccountList(Context context){
        this.accountList = SqliteDB.getInstance(context).getAllAccount();
    }

    /**
     * 获取所有账户名
     */

    public ArrayList<String> getAllAccountName(){
        ArrayList<String> accountNameArray = new ArrayList<String>();
        for(int i = 0; i < accountList.size(); i ++){
            accountNameArray.add(accountList.get(i).getName());
        }
        return accountNameArray;
    }


    /*********************************************************************************/
    /*********************************  统计操作 *************************************/
    /*********************************************************************************/
    /**
     * 设置前端要显示的账户
     * @param accountName
     */
    public void chooseAccount(String accountName){
        if(accountName != null && accountName.equals("全部账户")){
            allItemList = allItemListWithoutAccount;
        }else{
            allItemList = new ArrayList<Item>();
            for(int i = 0;i<allItemListWithoutAccount.size();i++){
                if(allItemListWithoutAccount.get(i).getAccount().equals(accountName)){
                    allItemList.add(allItemListWithoutAccount.get(i));
                }
            }
        }
        yearHasBeenCal = false;
        monthHasBeenCal = false;
        dayHasBeenCal = false;
    }

    /**
     * 计算整体统计信息
     */
    public void calculateDataAll(){
        for(int i = 0;i < accountList.size();i++){
            allAmount += accountList.get(i).getAsset();
            allIncome += accountList.get(i).getIncome();
            allExpend += accountList.get(i).getExpend();
        }
    }

    private void calIncomeAndExpend(){
        for(int i = 0;i<allItemListWithoutAccount.size();i++){
            Item item = allItemListWithoutAccount.get(i);
            if(item.getAmount() >= 0){
                item.setIncome(item.getAmount());
            }else{
                item.setExpend((-1)*item.getAmount());
            }
        }
    }

    /**
     * 按账户统计
     */
    public void calculateAccountItem(){
        //chooseAccount("全部账户");
        accountItemList = new ArrayList<Item>();
        for(int i = 0;i < accountList.size();i++){
            Item item = new Item();
            item.setAccount(accountList.get(i).getName());
            item.setAmount(accountList.get(i).getAsset());
            item.setIncome(accountList.get(i).getIncome());
            item.setExpend(accountList.get(i).getExpend());
            accountItemList.add(item);
        }
        accountHasBeenCal = (allItemList.size() != 0);
    }

    /**
     * 按月统计
     */
    public void calculateMonthItem(){
        int month = -1;
        int count = -1; //记录当前索引
        int year = 0;
        monthItemList = new ArrayList<Item>();
        for (int i = 0;i < allItemList.size();i++){
            if(month != allItemList.get(i).getMonth() || year != allItemList.get(i).getYear()){
                //新的月
                month = allItemList.get(i).getMonth();
                year = allItemList.get(i).getYear();
                Item item = new Item();
                item.setTimeManual(allItemList.get(i).getYear(),allItemList.get(i).getMonth(),1,0,0);
                item.setAmount(allItemList.get(i).getAmount());

                if(allItemList.get(i).getAmount() < 0){
                    item.setExpend( Math.abs(allItemList.get(i).getAmount()));
                }else{
                    item.setIncome( Math.abs(allItemList.get(i).getAmount()));
                }
                monthItemList.add(item);
                count ++;
            }else{
                Item item = allItemList.get(i);
                monthItemList.get(count).updateAmount(item.getAmount());
            }
        }
        monthHasBeenCal= (allItemList.size() != 0);
    }

    /**
     * 按年统计
     */
    public void calculateDayItem(){
        int count = -1;
        int day = 0;
        int year = 0;
        int month = 0;
        dayItemList = new ArrayList<Item>();
        for (int i = 0;i < allItemList.size();i++){
            if(day != allItemList.get(i).getDay()
                    || year != allItemList.get(i).getYear()
                    || month != allItemList.get(i).getMonth()){
                //新的日
                day = allItemList.get(i).getDay();
                year = allItemList.get(i).getYear();
                month = allItemList.get(i).getMonth();
                Item item = new Item();
                item.setTimeManual(year,month,day,0,0);
                item.setAmount(allItemList.get(i).getAmount());
                if(allItemList.get(i).getAmount() < 0){
                    item.setExpend( Math.abs(allItemList.get(i).getAmount()));
                }else{
                    item.setIncome( Math.abs(allItemList.get(i).getAmount()));
                }
                dayItemList.add(item);
                count ++;
            }else{
                Item item = allItemList.get(i);
                dayItemList.get(count).updateAmount(item.getAmount());
            }
        }
        dayHasBeenCal = (allItemList.size() != 0);

    }

    public void calculateYearItem(){
        int count = -1;
        int year = 0;
        yearItemList = new ArrayList<Item>();
        for (int i = 0;i < allItemList.size();i++){
            if(year != allItemList.get(i).getYear()){
                //新的年
                year = allItemList.get(i).getYear();
                Item item = new Item();
                item.setTimeManual(year,1,1,0,0);
                item.setAmount(allItemList.get(i).getAmount());
                if(allItemList.get(i).getAmount() < 0){
                    item.setExpend( Math.abs(allItemList.get(i).getAmount()));
                }else{
                    item.setIncome( Math.abs(allItemList.get(i).getAmount()));
                }
                yearItemList.add(item);
                count ++;
            }else{
                Item item = allItemList.get(i);
                yearItemList.get(count).updateAmount(item.getAmount());
            }
        }
        yearHasBeenCal = (allItemList.size() != 0);

    }


    /**
     * 获取某账户的所有账单
     * @param accountName
     * @return
     */
    public ArrayList<Item> geItemsOfAccount(String accountName) {
        ArrayList<Item> itemsOfAccout = new ArrayList<Item>();
        for(int i = 0;i<allItemList.size();i++){
            if(allItemList.get(i).getAccount() != null &&  allItemList.get(i).getAccount().equals(accountName)){
                itemsOfAccout.add( allItemList.get(i));
            }
        }
        return itemsOfAccout;
    }

    /**
     * 获取某成员的所有账单
     * @param member
     * @return
     */
    public ArrayList<Item> getItemsOfMember(String member) {
        ArrayList<Item> itemsOfMember = new ArrayList<Item>();
        for(int i = 0;i<allItemListWithoutAccount.size();i++){
            if(allItemListWithoutAccount.get(i).getMember() != null &&  allItemListWithoutAccount.get(i).getMember().equals(member)){
                itemsOfMember.add( allItemListWithoutAccount.get(i));
            }
        }
        return itemsOfMember;
    }

    /**
     * 获取某月的所有账单
     */
    public ArrayList<Item> getItemsOfMonth(int year, int month){
        ArrayList<Item> itemsOfMonth = new ArrayList<>();
        for(Item item:allItemListWithoutAccount){
            if(item.getMonth() == month && item.getYear() == year){
                itemsOfMonth.add(item);
            }
        }
        return itemsOfMonth;
    }

    /*********************************************************************************/
    /******************************* 图表操作(筛选) **********************************/
    /*********************************************************************************/
    /**
     * 在一定时间段内筛选某个类的所有账单
     * @return
     */
    public ArrayList<Item> getAllItemByTimeAndClass1(String className, Calendar startCalendar, Calendar endCalendar ){
        ArrayList<Item> targetItemList = new ArrayList<Item>();
        for(int i = 0;i < allItemListWithoutAccount.size();i ++){
            Item tempItem = allItemListWithoutAccount.get(i);
            if(tempItem.getClass1().equals(className)
                && tempItem.getTimeMill() >= startCalendar.getTimeInMillis()
                && tempItem.getTimeMill() <= endCalendar.getTimeInMillis() ){
                targetItemList.add(tempItem);
            }
        }
        return targetItemList;
    }


    /**
     * 在一定时间段内筛选并进行统计
     * @param objectList     用户自定义的对象名列表
     * @param mode           设置筛选对象
     * @param startCalendar  开始日期
     * @param endCalendar    结束日期
     * @return
     */
    public ArrayList<Item> getItemByTimeAndClass(ArrayList<String> objectList, int mode, Calendar startCalendar, Calendar endCalendar){
        ArrayList<Item> screenedItemList = new ArrayList<Item>();
        HashMap<String,Item> strItemMap = new HashMap<String,Item>();
        Item tempItem;
        if(objectList.size() == 0){
            Log.d("ItemManager", "getItemByTimeAndClass: no object selected");
            return screenedItemList;
        }
        for(int i = 0; i < objectList.size(); i++){
            String tempObj = objectList.get(i);
            strItemMap.put(tempObj,new Item());
            switch (mode){
                case SCREEN_MODE_CLASS1:
                    strItemMap.get(tempObj).setClass1(tempObj);
                    break;
                case SCREEN_MODE_CLASS2:
                    strItemMap.get(tempObj).setClass2(tempObj);
                    break;
                case SCREEN_MODE_MEMBER:
                    strItemMap.get(tempObj).setMember(tempObj);
                    break;
                case SCREEN_MODE_ACCOUNT:
                    strItemMap.get(tempObj).setAccount(tempObj);
                    break;
                default:
            }
        }
        for(int i = 0; i < allItemListWithoutAccount.size(); i++){
            tempItem = allItemListWithoutAccount.get(i);
            if(startCalendar.getTimeInMillis() <= tempItem.getTimeMill()
                && tempItem.getTimeMill() <= endCalendar.getTimeInMillis()){
                //更新收入、支出、合计金额
                switch (mode){
                    case SCREEN_MODE_CLASS1:
                        if(objectList.contains(tempItem.getClass1())){
                            strItemMap.get(tempItem.getClass1()).updateAmount(tempItem.getAmount());
                        }
                        break;
                    case SCREEN_MODE_CLASS2:
                        if(objectList.contains(tempItem.getClass2())) {
                            strItemMap.get(tempItem.getClass2()).updateAmount(tempItem.getAmount());
                        }
                        break;
                    case SCREEN_MODE_MEMBER:
                        if(objectList.contains(tempItem.getMember())){
                            strItemMap.get(tempItem.getMember()).updateAmount(tempItem.getAmount());
                        }
                        break;
                    case SCREEN_MODE_ACCOUNT:
                        if(objectList.contains(tempItem.getAccount())){
                            strItemMap.get(tempItem.getAccount()).updateAmount(tempItem.getAmount());
                        }
                        break;
                    default:
                }
            }
        }
        //将HashMap的value存ArrayList
        for(String key:strItemMap.keySet()){
            if(strItemMap.get(key).getAmount() != 0){
                screenedItemList.add(strItemMap.get(key));
            }
        }
        return  screenedItemList;
    }


    /**
     * 按时间段获取账单,此处自动设置粒度 小于3个月按天，否则按月
     */
    public ArrayList<Item> getItemByTime(Calendar startCalendar, Calendar endCalendar,int mode){
        ArrayList<Item> itemArrayList = new ArrayList<>();
        ArrayList<Item> tempAllList = new ArrayList<>();

        if(Math.abs(endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH))>3){
            if(!monthHasBeenCal){
                calculateMonthItem();
            }
            tempAllList = monthItemList;
        }else{
            if(!dayHasBeenCal){
                calculateDayItem();
            }
            tempAllList = dayItemList;
        }

        tempAllList = monthItemList;
        if(mode == MODE_EXPEND){
            for(int i = 0; i < tempAllList.size(); i++){
                Item tempItem = tempAllList.get(i);
                if(startCalendar.getTimeInMillis() <= tempItem.getTimeMill()
                        && tempItem.getTimeMill() <= endCalendar.getTimeInMillis()
                        && tempItem.getAmount() < 0){
                    itemArrayList.add(tempItem);
                }
            }
        }else if(mode == MODE_INCOME){
            for(int i = 0; i < tempAllList.size(); i++){
                Item tempItem = tempAllList.get(i);
                if(startCalendar.getTimeInMillis() <= tempItem.getTimeMill()
                        && tempItem.getTimeMill() <= endCalendar.getTimeInMillis()
                        && tempItem.getAmount() > 0){
                    itemArrayList.add(tempItem);
                }
            }
        }else if(mode == MODE_IN_AND_OUT){
            for(int i = 0; i < tempAllList.size(); i++){
                Item tempItem = tempAllList.get(i);
                if(startCalendar.getTimeInMillis() <= tempItem.getTimeMill()
                        && tempItem.getTimeMill() <= endCalendar.getTimeInMillis()){
                    itemArrayList.add(tempItem);
                }
            }
        }

        return itemArrayList;
    }

    public ArrayList<Item> getItemOfMonthCountByDay(int year,int month,int mode){
        int numOfDay = MyTimer.getDayOfMonth(year,month);
        ArrayList<Item> targetList = new ArrayList<>();
        HashMap<Integer,Item> tempMap = new HashMap<>();

        for(int i = 0;i < numOfDay;i ++){
            Item item = new Item();
            item.setTimeManual(year,month,i+1,0,0);
            tempMap.put(i+1,item);
        }
        if(mode == MODE_EXPEND){
            for(int i = 0;i < allItemList.size();i ++){
                Item tempItem = allItemList.get(i);
                if(tempItem.getMonth() != month || tempItem.getYear() != year || tempItem.getAmount() > 0){
                    continue;
                }else{
                    tempMap.get(tempItem.getDay()).updateAmount(tempItem.getAmount());
                }

            }
        }else if(mode == MODE_INCOME){
            for(int i = 0;i < allItemList.size();i ++){
                Item tempItem = allItemList.get(i);
                if(tempItem.getMonth() != month || tempItem.getYear() != year || tempItem.getAmount() < 0){
                    continue;
                }else{
                    tempMap.get(tempItem.getDay()).updateAmount(tempItem.getAmount());
                }
            }
        }
        for(int i : tempMap.keySet()){
            targetList.add(tempMap.get(i));
        }
        return targetList;
    }



    /**
     * 获取成员（支出）统计
     * @return
     */
    public ArrayList<Item> getMemberItemList(Calendar startCal, Calendar endCal){
        memberItemList = new ArrayList<>();
        HashMap<String,Item> memberMap = new HashMap<>();
        for(int i = 0;i < allItemListWithoutAccount.size();i ++){
            Item tempItem = allItemListWithoutAccount.get(i);
            if(memberMap.containsKey(tempItem.getMember())
                    && tempItem.getTimeMill() >= startCal.getTimeInMillis()
                    && tempItem.getTimeMill() <= endCal.getTimeInMillis()){
                memberMap.get(tempItem.getMember()).updateAmount(tempItem.getAmount());
            }else if( tempItem.getAmount() < 0 ){
                /**暂时只考虑支出，因为收入不分成员**/
                Item newItem = new Item();
                newItem.setMember(tempItem.getMember());
                newItem.updateAmount(tempItem.getAmount());
                newItem.setCal(tempItem.getCal());
                memberMap.put(tempItem.getMember(),newItem);
            }
        }
        for(String key:memberMap.keySet()){
            memberItemList.add(memberMap.get(key));
        }
        memberItemList.sort(new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                if(o1.getAmount() > o2.getAmount()){
                    return 1;
                }else{
                    return -1;
                }
            }
        });
        return  memberItemList;
    }



    /*********************** 提醒操作 ************************/
    /**
     * 获取最早的还款时间
     * @return
     */
    public Calendar getPayBackTime(){
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(0);
        for(int i = creditItemList.size() - 1 ;i >= 0;i--){
            Item tempItem = creditItemList.get(i);
            if(tempItem.getMode() == Item.MODE_CREDIT || tempItem.getMode() == Item.MODE_CREDIT_PAYBACK){
                calendar = tempItem.getPayBackCalendar();
            }
        }
        return calendar;
    }

    /******** 判断是否已经完成统计计算，避免重复计算 ********/
    public boolean isMonthHasBeenCal(){
        return monthHasBeenCal;
    }

    public boolean isYearHasBeenCal(){
        return  yearHasBeenCal;
    }

    public boolean isAccountHasBeenCal() {
        return accountHasBeenCal;
    }
    /********************************************************/



    public double getAllAmount() {
        return allAmount;
    }

    public double getAllExpend() {
        return allExpend;
    }

    public double getAllIncome() {
        return allIncome;
    }

    public ArrayList<Item> getMonthItemList() {
        return monthItemList;
    }

    public ArrayList<Item> getYearItemList() {
        return yearItemList;
    }

    public ArrayList<Item> getAccountItemList() {
        return accountItemList;
    }

    public ArrayList<Item> getAllItemListWithoutAccount(){
        return allItemListWithoutAccount;
    }

    public ArrayList<Item> getAllItemList() {
        return allItemList;
    }

    public ArrayList<Item> getCreditItemList() {
        return creditItemList;
    }

    private void sortItem(){
        this.allItemList.sort(new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                if(o1.getCal().getTimeInMillis() > o2.getCal().getTimeInMillis()){
                    return 1;
                }else{
                    return -1;
                }
            }
        });
    }

}
